package com.gtmc.gclub.chat.service;

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.gtmc.gclub.chat.bean.MyException;
import com.gtmc.gclub.chat.bean.Result;
import com.gtmc.gclub.chat.config.ChatConfigParam;
import com.gtmc.gclub.chat.config.SensorsAnalyInit;
import com.gtmc.gclub.chat.constants.ChatConstant;
import com.gtmc.gclub.chat.constants.CommonProperties;
import com.gtmc.gclub.chat.dao.TmDealerMapper;
import com.gtmc.gclub.chat.dao.TrUserEnterpriseMapper;
import com.gtmc.gclub.chat.dao.TtChatLogMapper;
import com.gtmc.gclub.chat.dao.WxChatLogMapper;
import com.gtmc.gclub.chat.dao.WxTokenMapper;
import com.gtmc.gclub.chat.dao.WxUserOwnerMapper;
import com.gtmc.gclub.chat.dto.ChatMsgDetailDto;
import com.gtmc.gclub.chat.dto.WxChatLogExportDto;
import com.gtmc.gclub.chat.dto.WxGzMessageDto;
import com.gtmc.gclub.chat.external.service.WeChatPushServiceInterface;
import com.gtmc.gclub.chat.jmessage.MessageOperator;
import com.gtmc.gclub.chat.jmessage.UserOperator;
import com.gtmc.gclub.chat.model.TmCarOwner;
import com.gtmc.gclub.chat.model.TmDealer;
import com.gtmc.gclub.chat.model.TmPotentialUser;
import com.gtmc.gclub.chat.model.TrUserEnterprise;
import com.gtmc.gclub.chat.model.TtChatLog;
import com.gtmc.gclub.chat.model.WxChatLog;
import com.gtmc.gclub.chat.model.WxUserOwner;
import com.gtmc.gclub.chat.util.DateUtil;
import com.gtmc.gclub.chat.util.MD5Util;
import com.gtmc.gclub.chat.util.RandomNum;
import com.gtmc.gclub.chat.vo.H5MessageVo;
import com.gtmc.gclub.chat.vo.WxChatLogExportVo;
import com.gtmc.gclub.chat.vo.TrUserEnterpriseVo;
import com.gtmc.gclub.common.WxMaterialTypeEnum;
import com.gtmc.gclub.common.WxUtil;
import com.gtmc.gclub.wx.dto.JmessAuth;
import com.gtmc.gclub.wx.dto.WxUserInfo;

@Service
@Transactional
public class WxUserService {
	private Logger logger = LoggerFactory.getLogger(this.getClass());
	@Autowired
	private WxUserOwnerMapper wxUserOwnerMapper;

	@Autowired
	private TrUserEnterpriseMapper trUserEnterpriseMapper;

	@Autowired
	private OwnerService ownerService;

	@Autowired
	private WxChatLogMapper wxChatLogMapper;

	@Autowired
	private MessageOperator messageOperator;

	@Autowired
	private CommonProperties commonProperties;

	@Autowired
	private UserOperator userOperator;

	@Autowired
	private WxTokenMapper wxTokenMapper;

	@Autowired
	private TmDealerMapper tmDealerMapper;

	@Autowired
	private WeChatPushServiceInterface weChatPushService;
	
	@Autowired
	private TtChatLogMapper ttChatLogMapper;
	
	/**
	 * 获取客户列表
	 * 
	 * @param pageCurrent
	 * @param pageSize
	 * @param userId
	 * @return
	 */
	public List<Map<String, Object>> getWxChatList(Integer userId, Integer status) {
		// PageHelper.startPage(pageCurrent, pageSize, true, false);
		WxUserOwner userOwner = new WxUserOwner();
		userOwner.setWxUserId(userId.toString());
		List<Map<String, Object>> list = wxUserOwnerMapper.getWxChatList(userId, status);
		// PageInfo<Map<String, Object>> pageInfo = new PageInfo<Map<String,
		// Object>>(list);
		return list;
	}

	/**
	 * 
	 * @author qianjs163@163.com
	 * @param id
	 * @return
	 */
	public int updateUserOwner(Integer id) {
		WxUserOwner customer = new WxUserOwner();
		customer.setId(id);
		customer.setWxViewTime(new Date());
		return wxUserOwnerMapper.updateBy(customer);
	}

	/**
	 * 查询用户-客户信息
	 * 
	 * @return
	 */
	public Map<String, Object> getUserInfo(String ownerCode, String userId) {
		TrUserEnterprise user = getWxChatUser(userId);
		WxUserOwner customer = getWxUserOwner(userId, ownerCode);
		updateUserOwner(customer.getId());
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("user", user);
		map.put("customer", customer);
		return map;
	}

	/**
	 * 获取聊天详细信息
	 * 
	 * @param userId
	 * @param ownerCode
	 * @param pageCurrent
	 * @param pageSize
	 * @return
	 */
	public List<Map<String, Object>> getWxChatTalk(String userId, String ownerCode, int pageCurrent, int pageSize,
			Integer chatId, Long lastTimes) {
		logger.info("获取聊天详情：getWxChatTalk");
		List<Map<String, Object>> rsList = new ArrayList<Map<String, Object>>();
		int startRow = pageCurrent > 0 ? (pageCurrent - 1) * pageSize : 0;
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("userId", userId);
		map.put("ownerCode", ownerCode);
		map.put("startRow", startRow);
		map.put("endRow", pageSize);
		map.put("chatId", chatId);
		int cn = wxChatLogMapper.getWxChatTalkCount(map);
		List<Map<String, Object>> list = wxChatLogMapper.getWxChatTalk(map);
		for (Map<String, Object> tempLog : list) {
			H5MessageVo messageEntity = new H5MessageVo();
			WxMaterialTypeEnum type = tempLog.get("contentType") == null ? null
					: WxMaterialTypeEnum.valueOf(String.valueOf(tempLog.get("contentType")));
			messageEntity.setType(type);
			// 经约定，所有单个媒体类的消息，没有内容，只有文件，则不设置content值，仅提供url等其他信息，供前端访问
			if (type == WxMaterialTypeEnum.text || type == WxMaterialTypeEnum.news
					|| type == WxMaterialTypeEnum.mpnews) {
				messageEntity
						.setContent(tempLog.get("content") == null ? null : String.valueOf(tempLog.get("content")));
			}
			messageEntity.setTitle(tempLog.get("title") == null ? null : String.valueOf(tempLog.get("title")));
			messageEntity.setUrl(tempLog.get("url") == null ? null : String.valueOf(tempLog.get("url")));
			tempLog.put("content", messageEntity);
		}
		boolean flag = false;
		if (list.size() == cn) {
			flag = true;
		}
		if (list.size() == 0) {
			return list;
		}
		// if (lastTimes != null) {
		// Date LastTime = new Date(lastTimes);
		// Map<String, Object> l = new HashMap<String, Object>();
		// l.put("lastTime", LastTime);
		// list.add(l);
		// }
		rsList.addAll(list);
		int j = 0;
		int k = list.size();
		for (int i = k; i > 0; i--) {
			Map<String, Object> first = list.get(i - 1);
			Date date1 = (Date) first.get("lastTime");
			long time1 = date1.getTime();
			Integer ss = (Integer) first.get("dateShow");
			if (ss == 1) {
				String showTime = DateUtil.getShowDate(date1, time1);
				Map<String, Object> m = new HashMap<String, Object>();
				m.put("time", showTime);
				rsList.add(i - 1, m);
				continue;
			}
			long time2 = 0;
			long time = 0;
			if (i == 1) {
				if (flag) {
					String showTime = DateUtil.getShowDate(date1, time1);
					Map<String, Object> m = new HashMap<String, Object>();
					m.put("time", showTime);
					rsList.add(0, m);
				}
				break;
			}
			Map<String, Object> second = list.get(i - 2);
			Date date2 = (Date) second.get("lastTime");
			time2 = date2.getTime();
			time = time1 - time2;
			if (time < 5 * 60 * 1000) {
				//
			} else {
				// 显示 time1
				String showTime = DateUtil.getShowDate(date1, time1);
				Map<String, Object> m = new HashMap<String, Object>();
				m.put("time", showTime);
				rsList.add(i - 1, m);
			}
		}
		// if (lastTimes != null)
		//
		// {
		// rsList.remove(rsList.size() - 1);
		// }

		// System.err.println(JSON.toJSONString(rsList));
		return rsList;

	}

	public List<Map<String, Object>> getWxChatLog(String userId, String userName, List<String> ownerCodes,
			Integer csType, String startDay, String endDay, List<String> dealerCodes, String sortField,
			String orderType, Integer pageCurrent, Integer pageSize) {
		logger.info("获取聊天详情：getWxChatLog");
		Map<String, Object> map = new HashMap<String, Object>();
		if (userId != null && !userId.trim().equals("")) {
			map.put("userId", userId);
		}
		if (userName != null && !userName.trim().equals("")) {
			map.put("userName", userName);

		}

		if (ownerCodes != null && ownerCodes.size() > 0) {
			// System.out.println("wuqi!!!! have ownercodes!" +
			// Arrays.toString(ownerCodes.toArray()));
			map.put("ownerCodes", ownerCodes);
		} else {
			// System.out.println("wuqi!!!! no ownercodes!");

		}

		if (dealerCodes != null && dealerCodes.size() > 0) {
			map.put("dealerCodes", dealerCodes);
		}

		if (csType != null) {
			map.put("csType", csType);
		}
		if (startDay != null && !startDay.trim().equals("")) {
			map.put("startDay", startDay + " 00:00:00");
		}
		if (endDay != null && !endDay.trim().equals("")) {
			map.put("endDay", endDay + " 23:59:59");
		}

		if (pageCurrent != null && pageSize != null) {
			Integer startRow = pageCurrent > 0 ? (pageCurrent - 1) * pageSize : 0;
			map.put("startRow", startRow);
			map.put("endRow", pageSize);
		}
		if (sortField != null && !sortField.trim().equals("")) {
			map.put("sortField", sortField);
		}
		if (orderType != null && !orderType.trim().equals("")) {
			map.put("orderType", orderType);
		}
		return wxChatLogMapper.getWxChatLog(map);

	}

	public List<Map<String, Object>> getWxChatLogtest(Integer pageCurrent, Integer pageSize) {
		logger.info("获取聊天详情：getWxChatLogtest");
		Map<String, Object> map = new HashMap<String, Object>();

		if (pageCurrent != null && pageSize != null) {
			Integer startRow = pageCurrent > 0 ? (pageCurrent - 1) * pageSize : 0;
			map.put("startRow", startRow);
			map.put("endRow", pageSize);
		}

		return wxChatLogMapper.getWxChatLog(map);

	}

	/**
	 * 获取客户列表
	 * 
	 * @param pageCurrent
	 * @param pageSize
	 * @return
	 */
	public List<Map<String, Object>> getUserOwnerList(List dealerCodes, List ownerCodes, List modelPhones,
			Integer csType, String ownerName, String sortField, String orderType, Integer pageCurrent,
			Integer pageSize) {
		logger.info("获取客服对应表：getUserOwnerList" + csType);
		//

		Map<String, Object> map = new HashMap<String, Object>();
		// if(ownerCode != null){
		// map.put("ownerCode", ownerCode);
		// }
		if (ownerName != null && !ownerName.trim().equals("")) {
			map.put("ownerName", ownerName);
		}
		if (ownerCodes != null && ownerCodes.size() > 0) {
			map.put("ownerCodes", ownerCodes);
		}
		if (modelPhones != null && modelPhones.size() > 0) {
			map.put("modelPhones", modelPhones);
		}

		if (csType != null) {
			map.put("csType", csType);
		}
		if (dealerCodes != null && dealerCodes.size() > 0) {
			map.put("dealerCodes", dealerCodes);
		}
		if (pageCurrent != null && pageSize != null) {
			Integer startRow = pageCurrent > 0 ? (pageCurrent - 1) * pageSize : 0;
			map.put("startRow", startRow);
			map.put("endRow", pageSize);
		}
		if (sortField != null && !sortField.trim().equals("")) {
			map.put("sortField", sortField);
		}
		if (orderType != null && !orderType.trim().equals("")) {
			map.put("orderType", orderType);
		}

		// 根据条件获取所有客服id :wx_user_id
		// TODO
		// List<Integer> userIds = new ArrayList();

		// List<Map<String, Object>> list =
		// wxUserOwnerMapper.getWxChatOwerList(map);
		List<Map<String, Object>> list = wxUserOwnerMapper.getWxChatOwerListUnite(map);
		return list;
	}

	/**
	 * 获取微信用户信息
	 * 
	 * @return
	 */
	public TrUserEnterprise getWxChatUser(String userId) {
		return trUserEnterpriseMapper.selectByPrimaryKey(new BigDecimal(userId));
	}

	/**
	 * 查询微信用户信息
	 * 
	 * @author qianjs163@163.com
	 * @param token
	 * @param userCode
	 * @return
	 */
	public TrUserEnterprise getFirstWxChatUser1(String token, String userCode) {
		logger.info("查询微信用户信息：getFirstWxChatUser");
		TrUserEnterprise user = new TrUserEnterprise();
		user.setWxUserId(userCode);
		TrUserEnterprise wxUser = trUserEnterpriseMapper.selectOne(user);
		return wxUser;
	}

	/**
	 * 首次登录获取微信用户信息
	 * 
	 * @return
	 */
	public TrUserEnterprise getFirstWxChatUser(String token, String userCode) {
		logger.info("查询微信用户信息：getFirstWxChatUser");
		TrUserEnterprise user = new TrUserEnterprise();
		user.setWxUserId(userCode);
		TrUserEnterprise wxUser = trUserEnterpriseMapper.selectOne(user);
		if (wxUser == null) {
			wxUser = new TrUserEnterprise();
			WxUserInfo userInfo = WxUtil.getWxUserInfo(token, userCode);
			if (!"0".equals(String.valueOf(userInfo.getErrcode()))) {
				logger.error("系统异常:" + userInfo.getErrmsg());
				throw new MyException("permission");
			}
			List<Integer> list = userInfo.getDepartment();
			if (!(userInfo.getAvatar() == null || "".equals(userInfo.getAvatar()))) {
				// wxUser.setIconsPhoto(userInfo.getAvatar() +
				// ChatConstant.WX_SMALL_IMAGE);
				user.setIconsPhoto(userInfo.getAvatar());
			} else {
				user.setIconsPhoto("");
			}
			boolean flag = WxUtil.getServerType(token, userCode, commonProperties.tagidBefore);
			Byte t = null;
			if (flag) {
				t = ChatConstant.SHOU_QIAN;
			} else if (WxUtil.getServerType(token, userCode, commonProperties.tagidAfter)) {
				t = ChatConstant.SHOU_HOU;
			} else {
				logger.error(userCode + "标签职位不符合定义");
				throw new MyException("permission");
			}
			wxUser.setWxUserId(userCode);
			wxUser.setWeixinName(userInfo.getName());
			Result<Map> result = userOperator.registerAdmins(ChatConstant.IMESSAGE_PREFIX + userCode,
					commonProperties.pwd);
			if (!"1".equals(String.valueOf(result.getReturnFlag()))) {
				// 注册失败
				logger.error(ChatConstant.IMESSAGE_PREFIX + userCode + result.getErrorMsg());
				user.setJmessageCode("");
			} else {
				wxUser.setJmessageCode(ChatConstant.IMESSAGE_PREFIX + userCode);
			}
			String code = WxUtil.getDealerCode(token, userInfo.getDepartment().get(0));

			wxUser.setDealerCode(code);
			wxUser.setDealerCdType(new BigDecimal(t));

			// 获取销售店信息 wuqi
			TmDealer dealer = new TmDealer();
			dealer.setDealerCode(code);
			dealer = tmDealerMapper.selectOne(dealer);
			if (dealer != null) {
				wxUser.setDealerName(dealer.getDealerName());
			}
			int i = trUserEnterpriseMapper.insertUser(wxUser);
			// return wxUser;
		} else {
			boolean flag = false;
			// 补销售店名
			if (wxUser.getDealerName() == null || wxUser.getDealerName().trim().equals("")) {
				// 获取销售店信息 wuqi
				TmDealer dealer = new TmDealer();
				dealer.setDealerCode(wxUser.getDealerCode());
				dealer = tmDealerMapper.selectOne(dealer);
				if (dealer != null) {
					wxUser.setDealerName(dealer.getDealerName());
				}
				flag = true;

			}
			// 补jmessage账号
			if (wxUser.getJmessageCode() == null || wxUser.getJmessageCode().trim().equals("")) {
				Result<Map> result = userOperator.registerAdmins(ChatConstant.IMESSAGE_PREFIX + userCode,
						commonProperties.pwd);
				if (!"1".equals(String.valueOf(result.getReturnFlag()))) {
					// 注册失败
					logger.error(ChatConstant.IMESSAGE_PREFIX + userCode + result.getErrorMsg());
				} else {
					wxUser.setJmessageCode(ChatConstant.IMESSAGE_PREFIX + userCode);
				}
				flag = true;
			}
			if (flag) {
				int i = trUserEnterpriseMapper.updateByPrimaryKeySelective(wxUser);
			}
		}
		return wxUser;
	}

	/**
	 * 获取app用户信息
	 * 
	 * @return
	 */
	public WxUserOwner getWxUserOwner(String userId, String ownerCode) {
		WxUserOwner obj = new WxUserOwner();
		obj.setWxUserId(userId);
		obj.setOwnerCode(ownerCode);
		obj.setStatus(WxUserOwner.STATUS_USEFUL);
		return wxUserOwnerMapper.selectOne(obj);
	}

	/**
	 * 查新app -客户jmessage帐号
	 * 
	 * @param userId
	 * @param ownerCode
	 * @return
	 */
	public Map<String, Object> getJmessage(String userId, String ownerCode) {
		logger.info("查询jmessage帐号:getJmessage");
		TrUserEnterprise user = getWxChatUser(userId);
		WxUserOwner customer = getWxUserOwner(userId, ownerCode);
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("user", user.getJmessageCode());
		map.put("customer", customer);
		map.put("userId", user.getId());
		// map.put("waId", customer.getId());
		return map;
	}

	/**
	 * 向微信用户发送消息 发送微信客户的message信息
	 * 
	 * @param map
	 * @return
	 */
	public Result<Map> sendMessage2(String content, String userId, String ownerCode, Integer dateShow) {
		logger.info("发送message信息：sendMessage");
		TrUserEnterprise user = getWxChatUser(userId);
		WxUserOwner customer = getWxUserOwner(userId, ownerCode);
		int num = customer.getWxActiveNum();
//		int activeNum = commonProperties.activeNum;
//		if (num == activeNum) {
//			return new Result<Map>(0, null, "您只能在用户回复后发送3条消息哦");
//		}
		// 先插入
		WxChatLog log = new WxChatLog();
		log.setContent(content);
		log.setCrtTime(new Date());
		log.setDirection(ChatConstant.CHAT_DIRECTION_WX);
		log.setWxUserId(Integer.valueOf(userId));
		log.setOwnerCode(customer.getOwnerCode());
		log.setSessionId(customer.getId());
		log.setDateShow(dateShow);
		int i = wxChatLogMapper.insertBase(log);
		// Result<Map> result =
		// messageOperator.sendSingleTextByAdmin(customer.getOwnerCode(),
		// user.getImessageCode(),
		// content);
		String name = user.getDealerName().replaceAll("广汽丰田", "") + "-" + user.getWeixinName();
		Result<Map> result = messageOperator.sendSingleTextByAdminWx(customer.getOwnerCode(), user.getJmessageCode(),
				content, name);
		if ("1".equals(String.valueOf(result.getReturnFlag()))) {
			// 更新发送信息
			Long msgId = (Long) result.getData().get("msg_id");
			log.setMsgId(msgId);
			int n = wxChatLogMapper.updateByPrimaryKeySelective(log);
			// 更新WxUserOwner表
			WxUserOwner wu = new WxUserOwner();
			wu.setId(customer.getId());
			wu.setDirection(ChatConstant.CHAT_DIRECTION_WX);
			wu.setLastContent(content);
			wu.setLastTime(new Date());
			// wu.setStatus(WxUserOwner.STATUS_USEFUL);
			int oldSessionId = customer.getSessionId();
			if (new Date().getTime() - customer.getLastTime().getTime() > 3 * 60 * 1000) {
				oldSessionId++;
			}
			wu.setSessionId(oldSessionId);
			num++;
			wu.setWxActiveNum(num);
			int j = wxUserOwnerMapper.updateBy(wu);
		} else {
			// 发送失败，回滚事务
			throw new MyException("系统异常");
		}

		// 神策发送消息
		// try {
		// Map<String, Object> properties = new HashMap<String, Object>();
		// // 客服类型 销售客服/售后客服
		// properties.put("serviceType", user.getDealerCsType() == 0 ? "销售客服" : "售后客服");
		// // 发送方（用户，客服）
		// properties.put("sender", "客服");
		// // 销售店名称
		// properties.put("dealer_name", user.getDealerName());
		// // 销售店code
		// properties.put("dealer_code", user.getDealerCode());
		// TmCarOwner owner = new TmCarOwner();
		// owner.setPhone(ownerCode);// 使用电话做code
		// owner = ownerService.getOne(owner);
		// if (owner == null) {
		// return new Result(10022, null, "no app user!");
		// }
		// SensorsAnalyInit.sa.track(owner.getUserId().toString(), true,
		// "OnlineConsultationService", properties);
		// } catch (Exception e) {
		// logger.error("<messagePush>神策埋线发生异常：", e);
		// }
		return result;
	}

	/**
	 * 发送微信客户的message信息
	 * 
	 * @param map
	 * @return
	 */
	public Result<Map> sendMessage(Map<String, Object> map) {
		logger.info("发送message信息：sendMessage");
		WxUserOwner customer = (WxUserOwner) map.get("customer");
		int num = customer.getWxActiveNum();
//		int activeNum = commonProperties.activeNum;
//		if (num == activeNum) {
//			return new Result<Map>(0, null, "您只能在用户回复后发送3条消息哦");
//		}
		// 先插入
		WxChatLog log = new WxChatLog();
		log.setContent((String) map.get("content"));
		log.setCrtTime(new Date());
		log.setDirection(ChatConstant.CHAT_DIRECTION_WX);
		log.setWxUserId((Integer) map.get("userId"));
		log.setOwnerCode(customer.getOwnerCode());
		log.setSessionId(customer.getId());
		int i = wxChatLogMapper.insertBase(log);
		Result<Map> result = messageOperator.sendSingleTextByAdmin(customer.getOwnerCode(), (String) map.get("user"),
				(String) map.get("content"));
		if ("1".equals(String.valueOf(result.getReturnFlag()))) {
			// 更新发送信息
			Long msgId = (Long) result.getData().get("msg_id");
			log.setMsgId(msgId);
			int n = wxChatLogMapper.updateByPrimaryKeySelective(log);
			// 更新WxUserOwner表
			WxUserOwner wu = new WxUserOwner();
			wu.setId(customer.getId());
			wu.setDirection(ChatConstant.CHAT_DIRECTION_WX);
			wu.setLastContent((String) map.get("content"));
			wu.setLastTime(new Date());
			int oldSessionId = customer.getSessionId();
			if (new Date().getTime() - customer.getLastTime().getTime() > 3 * 60 * 1000) {
				oldSessionId++;
			}
			wu.setSessionId(oldSessionId);
			num++;
			wu.setWxActiveNum(num);
			int j = wxUserOwnerMapper.updateBy(wu);
		} else {
			// 发送失败，回滚事务
			throw new MyException("系统异常");
		}
		return result;
	}

	/**
	 * 获取imessage的有效签名
	 * 
	 * @return
	 */
	public JmessAuth getJmessAuth() {
		logger.info("获取imessage的有效签名:getJmessAuth");
		String radom = RandomNum.createRandomString(20);
		long time = System.currentTimeMillis();
		String str = "appkey=" + commonProperties.appkey + "&timestamp=" + time + "&random_str=" + radom + "&key="
				+ commonProperties.masterSecret;
		String signature = MD5Util.MD5(str);
		JmessAuth auth = new JmessAuth();
		auth.setAppkey(commonProperties.appkey);
		auth.setRandom_str(radom);
		auth.setSignature(signature);
		auth.setTimestamp(String.valueOf(time));
		return auth;
	}

	public WxUserOwner getOne(WxUserOwner user) {
		List<WxUserOwner> chats = wxUserOwnerMapper.select(user);
		if (CollectionUtils.isEmpty(chats)) {
			return null;
		}
		if (chats.size() > 1) {
			logger.debug("一个用户只能对应一个客服，此处" + user.getOwnerCode() + "用户对应了多个客服+" + chats);
			// 这里要修正一下错误数据，把多余的聊天链接状态修改掉
			
		}

		return chats.get(0);
//		return wxUserOwnerMapper.selectOne(user);
	}

	public int save(WxUserOwner user) {
		int i = wxUserOwnerMapper.insert(user);

		return i;
	}

	public int updateData(WxUserOwner user) {
		int i = wxUserOwnerMapper.updateByPrimaryKeySelective(user);
		return i;
	}

	public int updateDataNullUpdate(WxUserOwner user) {
		int i = wxUserOwnerMapper.updateByPrimaryKey(user);
		return i;
	}

	public Integer upDateShow(Long msgId) {

		int i = wxChatLogMapper.upDateShow(msgId);
		return i;
	}

	/**
	 * H5客服回复给用户消息 TrUserEnterprise user 客服信息（具体的客服信息，要去TM_USER中取） WxUserOwner
	 * customer 客服用户对应关系表 TmPotentialUser wxUser微信用户表
	 * 
	 * @param map
	 * @return
	 * @throws Exception 
	 */
	public Result<String> sendMessageToWxPublish(WxGzMessageDto wxmsgDto, TrUserEnterprise user, WxUserOwner customer,TmPotentialUser wxUser) throws Exception {
		logger.info("发送message信息：sendMessageToWxPublish开始");
		logger.info("客服：" + user);
		logger.info("客服用户关系链接：" + customer);
		logger.info("公众号用户：" + wxUser);
		String content = wxmsgDto.getContent();
		Integer dateShow = StringUtils.isEmpty(wxmsgDto.getDateShow()) ? 1 : Integer.valueOf(wxmsgDto.getDateShow());
		WxMaterialTypeEnum messageType = WxMaterialTypeEnum.valueOf(wxmsgDto.getMsgType());
		int num = customer.getWxActiveNum();
//		int activeNum = commonProperties.activeNum;
//		if (num == activeNum) {
//			return new Result<String>(0, null, "您只能在用户回复后发送3条消息哦");
//		}
		// 先插入聊天记录
		WxChatLog log = new WxChatLog();
		log.setContent(content);
		log.setContentType(messageType);
		log.setCrtTime(new Date());
		log.setDirection(ChatConstant.CHAT_DIRECTION_WX);
		log.setWxUserId(user.getId().intValue());
		log.setOwnerCode(customer.getOwnerCode());
		log.setSessionId(customer.getId());
		log.setDateShow(dateShow);
		logger.debug("插入消息记录：" + log);
		int i = wxChatLogMapper.insertBase(log);
		TtChatLog chatLog = new TtChatLog();
		chatLog.setContent(content);
		chatLog.setContentType(messageType.name());
		chatLog.setCreateDate(new Date());
		chatLog.setPotentialUserId(customer.getOwnerCode());
		chatLog.setServiceId(user.getId().intValue());
		chatLog.setSendType(3);
		logger.debug("插入消息记录：" + chatLog);
		ttChatLogMapper.insert(chatLog);
		// 然后把消息传递给公众号微服务
		String name = user.getDealerName().replaceAll("广汽丰田", "") + "-" + user.getWeixinName();
		// Result<Map> result =
		// messageOperator.sendSingleTextByAdminWx(customer.getOwnerCode(),
		// user.getJmessageCode(),
		// content, name);
		WxGzMessageDto wxgzMsg = new WxGzMessageDto();
		wxgzMsg.setFromUserName(user.getId().toString());
		wxgzMsg.setToUserName(wxUser.getDeviceOpenId());
		wxgzMsg.setMsgType(messageType.name());
		wxgzMsg.setContent(content);
		wxgzMsg.setMediaId(messageType == WxMaterialTypeEnum.text ? null : content);
		// 此处需要按照不同的媒体消息类型，增加相应的参数，如有必要，需从微信取媒体消息属性设置。如务必要，则可从数据库中取值
		logger.debug("调用公众号微服务，发送消息：" + wxgzMsg);
		// 直接通过微服务之间的调用，把消息发送到公众号服务
		Map<String, Object> wxpublishResult = weChatPushService.sendWxgzMsg(wxgzMsg);
		logger.debug("发送给用户消息发送结果：" + wxpublishResult);
		// 由于客服是企业号、PC端双在线，系统提供了两个极光账号，一个极光账号发送消息，另外一个极光账号要收到
		String targetJmessageCode = user.getJmessageCode() ;
		if(StringUtils.equals(wxmsgDto.getJmessageCode(), user.getJmessageCode())) {
			targetJmessageCode = user.getWxJmessageCode();
		}
		H5MessageVo messageVo = new H5MessageVo();
		messageVo.setFromUser(wxUser);
		messageVo.setContent(content);
		messageVo.setType(WxMaterialTypeEnum.text);
		messageVo.setMessageSource(H5MessageVo.MESSAGE_FROM_H5);
//		if(WxMaterialTypeEnum.text!=msgType) {
//			messageVo.setUrl(url);
//		}
		Result<Map> h5result = messageOperator.sendSingleTextByAdmin(targetJmessageCode, wxUser.getPotentialUserId().toString(), JSON.toJSONString(messageVo));
		if (h5result.getReturnFlag() != 1) {
			throw new MyException("Send message to h5 failur!!!");
		}
		Result<String> result = new Result(Integer.valueOf(String.valueOf(wxpublishResult.get("errorCode"))),
				String.valueOf(wxpublishResult.get("errorMsg")));
		if ("200".equals(String.valueOf(result.getReturnFlag()))) {
			// 更新发送信息:客服回复给用户的消息，不通过极光，通过公众号发送，无msg_id
			// Long msgId = (Long) result.getData().get("msg_id");
			// log.setMsgId(msgId);
			// int n = wxChatLogMapper.updateByPrimaryKeySelective(log);
			// 更新WxUserOwner表
			WxUserOwner wu = new WxUserOwner();
			wu.setId(customer.getId());
			wu.setDirection(ChatConstant.CHAT_DIRECTION_WX);
			wu.setLastContent(content);
			wu.setLastContentType(messageType);
			wu.setLastTime(new Date());
			int oldSessionId = customer.getSessionId();
			if (new Date().getTime() - customer.getLastTime().getTime() > 3 * 60 * 1000) {
				oldSessionId++;
			}
			wu.setSessionId(oldSessionId);
			num++;
			wu.setWxActiveNum(num);
			logger.debug("更新用户-客服关系表：" + wu);
			int j = wxUserOwnerMapper.updateBy(wu);
		} else {
			// 发送失败，回滚事务
			throw new MyException("系统异常");
		}
		logger.info("发送message信息：sendMessageToWxPublish结束");
		return result;
	}

	/**
	 * H5客服回复给用户消息 TrUserEnterprise user 客服信息（具体的客服信息，要去TM_USER中取） WxUserOwner
	 * customer 客服用户对应关系表 TmPotentialUser wxUser微信用户表
	 * 
	 * @param map
	 * @return
	 */
	public Result<String> sendMediaMessageToWxPublish(TrUserEnterprise user, WxUserOwner customer,
			TmPotentialUser wxUser, Integer dateShow, WxGzMessageDto wxmsgDto) {
		logger.info("发送message信息：sendMediaMessageToWxPublish开始");
		logger.info("客服：" + user);
		logger.info("客服用户关系链接：" + customer);
		logger.info("公众号用户：" + wxUser);
		int num = customer.getWxActiveNum();
//		int activeNum = commonProperties.activeNum;
//		if (num == activeNum) {
//			return new Result<String>(0, null, "您只能在用户回复后发送3条消息哦");
//		}
		// 先插入聊天记录
		WxChatLog log = new WxChatLog();
		log.setContent(wxmsgDto.getContent());
		log.setContentType(wxmsgDto.getMsgType());
		log.setCrtTime(new Date());
		log.setDirection(ChatConstant.CHAT_DIRECTION_WX);
		log.setWxUserId(user.getId().intValue());
		log.setOwnerCode(customer.getOwnerCode());
		log.setSessionId(customer.getId());
		log.setDateShow(dateShow);
		log.setTitle(wxmsgDto.getTitle());
		log.setUrl(wxmsgDto.getContent());
		// 这里有必要添加一个消息类型
		logger.debug("插入消息记录：" + log);
		int i = wxChatLogMapper.insertBase(log);
		TtChatLog chatLog = new TtChatLog();
		chatLog.setContent(wxmsgDto.getContent());
		chatLog.setContentType(wxmsgDto.getMsgType());
		chatLog.setCreateDate(new Date());
		chatLog.setPotentialUserId(customer.getOwnerCode());
		chatLog.setServiceId(user.getId().intValue());
		chatLog.setSendType(3);
		logger.debug("插入消息记录：" + chatLog);
		ttChatLogMapper.insert(chatLog);
		// 然后把消息传递给公众号微服务
		String name = user.getDealerName().replaceAll("广汽丰田", "") + "-" + user.getWeixinName();
		wxmsgDto.setFromUserName(user.getId().toString());
		wxmsgDto.setToUserName(wxUser.getDeviceOpenId());
		// content为空的情况下，发送给微信会报错
		if(StringUtils.isEmpty(wxmsgDto.getContent())) {
			wxmsgDto.setContent(wxmsgDto.getMsgType());
		}
		logger.debug("调用公众号微服务，发送消息：" + wxmsgDto);
		Map<String, Object> wxpublishResult = weChatPushService.sendWxgzMsg(wxmsgDto);
		logger.debug("向微信用户消息发送结果：" + wxpublishResult);
		
		// 由于客服是企业号、PC端双在线，系统提供了两个极光账号，一个极光账号发送消息，另外一个极光账号要收到
		String targetJmessageCode = user.getJmessageCode() ;
		if(StringUtils.equals(wxmsgDto.getJmessageCode(), user.getJmessageCode())) {
			targetJmessageCode = user.getWxJmessageCode();
		}
		H5MessageVo messageVo = new H5MessageVo();
		messageVo.setFromUser(wxUser);
		// 经商定，一般的媒体消息，不需要content
//		messageVo.setContent(wxmsgDto.getContent());
		messageVo.setType(WxMaterialTypeEnum.valueOf(wxmsgDto.getMsgType()));
		messageVo.setMessageSource(H5MessageVo.MESSAGE_FROM_H5);
		messageVo.setTitle(wxmsgDto.getTitle());
		if(!StringUtils.equals(WxMaterialTypeEnum.text.name(), wxmsgDto.getMsgType())) {
			messageVo.setUrl(wxmsgDto.getContent());
		}
		logger.debug("前段传来的jmessageCode:"+wxmsgDto.getJmessageCode()+";最终要转发的jmessageCode:"+targetJmessageCode);
		Result<Map> h5result = messageOperator.sendSingleTextByAdmin(targetJmessageCode, wxUser.getPotentialUserId().toString(), JSON.toJSONString(messageVo));
		if(h5result!=null) {
			logger.debug("同步到客服另一端结果："+h5result.getReturnFlag()+":"+h5result.getErrorMsg());
		}else {
			logger.error("极光未返回结果");
		}
		if (h5result.getReturnFlag() != 1) {
			logger.error("Send message to h5 failur!!!");
			throw new MyException("Send message to h5 failur!!!");
		}
		
		Result<String> result = new Result(Integer.valueOf(String.valueOf(wxpublishResult.get("errorCode"))),
				String.valueOf(wxpublishResult.get("errorMsg")));
		if ("200".equals(String.valueOf(result.getReturnFlag()))) {
			// 更新发送信息:客服回复给用户的消息，不通过极光，通过公众号发送，无msg_id
			// Long msgId = (Long) result.getData().get("msg_id");
			// log.setMsgId(msgId);
			// int n = wxChatLogMapper.updateByPrimaryKeySelective(log);
			// 更新WxUserOwner表
			WxUserOwner wu = new WxUserOwner();
			wu.setId(customer.getId());
			wu.setDirection(ChatConstant.CHAT_DIRECTION_WX);
			wu.setLastContent(wxmsgDto.getContent());
			wu.setLastContentType(wxmsgDto.getMsgType());
			wu.setLastContentTitle(wxmsgDto.getTitle());
			wu.setLastContentUrl(wxmsgDto.getContent());
			wu.setLastTime(new Date());
			int oldSessionId = customer.getSessionId();
			if (new Date().getTime() - customer.getLastTime().getTime() > 3 * 60 * 1000) {
				oldSessionId++;
			}
			wu.setSessionId(oldSessionId);
			num++;
			wu.setWxActiveNum(num);
			logger.debug("更新用户-客服关系表：" + wu);
			int j = wxUserOwnerMapper.updateBy(wu);
		} else {
			logger.error("Send message failur!!!");
			// 发送失败，回滚事务
			throw new MyException("系统异常");
		}
		logger.info("发送message信息：sendMessageToWxPublish结束");
		return result;
	}

	/**
	 * 获取指定客服有效对应人数，按照从少到多的顺序排序
	 * 
	 * @return 客服对象
	 */
	public List<String> getLeisurestChat(List<TrUserEnterprise> allInlineChatList) {
		List<String> chatUsers = new ArrayList<String>();
		for (TrUserEnterprise tempChat : allInlineChatList) {
			chatUsers.add(tempChat.getId() + "");
		}
		logger.debug("开始获取客服及其对应人数：" + chatUsers);
		List<Map<String, Object>> chatStatusByChatList = wxUserOwnerMapper.getChatStatusByChatList(chatUsers, 1, null,
				null, null, null);
		logger.debug("查询出客服和对应人数集合：" + chatStatusByChatList);
		List<String> chatStatusByChatListIds = new ArrayList<String>();
		for (Map<String, Object> tempChatDetail : chatStatusByChatList) {
			chatStatusByChatListIds.add(String.valueOf(tempChatDetail.get("WX_USER_ID")));
		}
		logger.debug("整理出客服对应表中的所有客服ID:" + chatStatusByChatListIds);
		List<String> relateChatUsers = new ArrayList<String>();
		for (Map<String, Object> tempChatRela : chatStatusByChatList) {
			if (Integer.valueOf(String.valueOf(tempChatRela.get("SCOUNT"))) < ChatConfigParam.CHAT_MAX_CNUM) {
				relateChatUsers.add(String.valueOf(tempChatRela.get("WX_USER_ID")));
			}
		}
		logger.debug("根据客服对应最大人数筛选出符合条件的客服ID" + relateChatUsers);
		List<String> noRelateChatUsers = (List<String>) CollectionUtils.subtract(chatUsers, chatStatusByChatListIds);
		logger.debug("计算出没有出现在客服用户对应表中的客服:" + noRelateChatUsers);
		if (CollectionUtils.isNotEmpty(noRelateChatUsers)) {
			// 如果没有出现在客服用户对应表中的客服集合不为空，则返回的空闲客服应是：首先为没有出现在客服用户对应表中的客服，其次为出现在客服用户对应表中的空闲客服
			List<String> leisurestChats = new ArrayList<String>();
			leisurestChats.addAll(noRelateChatUsers);
			leisurestChats.addAll(relateChatUsers);
			return leisurestChats;
		} else {
			return relateChatUsers;
		}
	}

	/**
	 * 解除用户可客服之间的聊天关联
	 * 
	 * @param chatId
	 *            客服ID
	 * @param ownerCode
	 *            用户code
	 */
	public void deleteChatOwnerRel(Integer chatId, String ownerCode) {
		wxUserOwnerMapper.deleteChatOwnerRel(chatId, ownerCode);
	}

	/**
	 * 根据id集合获取客服集合
	 * 
	 * @param ids
	 * @return
	 * @throws Exception
	 */
	public List<TrUserEnterpriseVo> queryChatsByIds(List<String> ids) throws Exception {
		List<TrUserEnterprise> resEntity = trUserEnterpriseMapper.getChatUsersByPrimaryKeys(ids);
		List<TrUserEnterpriseVo> resVo = new ArrayList<TrUserEnterpriseVo>();
		for (TrUserEnterprise tempEntity : resEntity) {
			TrUserEnterpriseVo tempVo = new TrUserEnterpriseVo();
			BeanUtils.copyProperties(tempVo, tempEntity);
			resVo.add(tempVo);
		}
		return resVo;
	}

	/**
	 * 强制建立链接：userId客服ID,owner用户ID
	 * 
	 * @param userId
	 * @param owner
	 * @param chatQueueUserMsg
	 *            消息队列实体
	 */
	public boolean coerceCreateConnect(Integer userId, TmPotentialUser owner, String message,
			WxMaterialTypeEnum msgType) {
		// 强制建立链接之前，首先判断该链接是否存在，防止重复建立链接
		logger.debug("强制建立链接开始");
		WxUserOwner createConnect = new WxUserOwner();
		createConnect.setOwnerCode(owner.getPotentialUserId().toString());
		createConnect.setWxUserId(userId.toString());
		createConnect.setDirection(WxUserOwner.STATUS_USEFUL.byteValue());// 1为微信用户发起的
		createConnect.setFirstTime(new Date());
		createConnect.setLastTime(new Date());
		createConnect.setOwnerIcon(owner.getHeadImgurl());
		createConnect.setOwnerImessageCode(owner.getJmessageCode());
		createConnect.setOwnerName(owner.getNickname());
		createConnect.setStatus(WxUserOwner.STATUS_USEFUL);
		createConnect.setWxActiveNum(0);
		createConnect.setLastContent(message);
		createConnect.setLastContentType(msgType.name());
		createConnect.setSessionId(1);
		createConnect.setWxViewTime(new Date());
		int res = wxUserOwnerMapper.insert(createConnect);
		logger.debug("强制建立链接结束：" + createConnect);
		logger.debug("强制建立链接结束：" + res);
		return res > 0;
	}
	
	public List<WxChatLogExportVo> exportWxChatTalk(WxChatLogExportDto searchDto){
		return wxChatLogMapper.exportWxChatTalk(searchDto);
	}

}
